package com.bawei.java.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @Author : yaotianxue
 * @Time : On 2023/5/24 11:17
 * @Description : ReflectTest反射
 */
public class ReflectTest {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        //1.获得class对象，三种方式
        Class class1 = Class.forName("com.bawei.java.reflect.Student");
        Class class2 = Student.class;
        Class class3 = new Student().getClass();
        //Student.java-->Student.class->类只会被加载一次--》双亲委托机制
        System.out.println(class1==class2);
        System.out.println(class2==class3);

        //2.获得构造
        Constructor[] constructors = class1.getConstructors();//公开+继承父类的构造
        Constructor[] declaredConstructors = class1.getDeclaredConstructors();//公开+私有+没有继承父类的构造
        Constructor constructor = class1.getConstructor();//获得指定的构造：公开+继承父类的构造
        Constructor declaredConstructor = class1.getDeclaredConstructor(String.class, int.class);//获得指定的构造:公开+私有+没有继承父类的构造
        //使用构造创建对象
        Student student1 = (Student) constructor.newInstance();
        declaredConstructor.setAccessible(true);//私有调用前设置暴力访问
        Student student2 = (Student) declaredConstructor.newInstance("柴少龙", 18);

        //3.获得方法
        Method[] methods = class1.getMethods();//公开+继承父类的方法
        Method[] declaredMethods = class1.getDeclaredMethods();//公开+私有+没有继承父类的方法
        Method showAge = class1.getMethod("showAge", String.class);//获得指定方法：公开+继承父类的方法
        Method showName = class1.getDeclaredMethod("showName");//获得指定方法：公开+私有+没有继承父类的方法
        //调用方法
        showAge.invoke(student2,"八维");
        showName.setAccessible(true);//私有调用前设置暴力访问
        showName.invoke(student2);


        //4.获得属性
        Field[] fields = class1.getFields();//公开+继承父类的属性
        Field[] declaredFields = class1.getDeclaredFields();//公开+私有+没有继承父类的属性
        Field age = class1.getField("age");//获得指定属性：公开+继承父类
        Field name = class1.getDeclaredField("name");//获得指定属性：公开+私有+没有继承父类的方法
        //为属性赋值
        age.set(student2,28);//设置属性的值
        System.out.println(age.get(student2)+"");//获得属性的值
        name.setAccessible(true);//私有调用前设置暴力访问
        name.set(student2,"新的名字");
        System.out.println(name.get(student2)+"");//获得属性的值


    }
}
